package com.hth.stockspiderv3;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.google.common.collect.Lists;
import com.hth.stockspiderv3.po.*;
import com.hth.stockspiderv3.repository.StockBlockMapper;
import com.hth.stockspiderv3.repository.StockIndexMapper;
import com.hth.stockspiderv3.repository.StockInfoMapper;
import com.hth.stockspiderv3.vo.KLineParseVo;
import com.hth.stockspiderv3.vo.StockBasicVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class Spider {
    @Autowired
    private StockIndexMapper stockIndexMapper;
    @Autowired
    private StockInfoMapper stockInfoMapper;
    @Autowired
    private StockBlockMapper stockBlockMapper;

    private static Spider spider = null;
    private final HttpHandler httpHandler = new HttpHandler();
    private static final List<String> codeList = Lists.newArrayList("001696", "001896", "001979", "001965");
    private static final List<String> mainBlockCodeList = Lists.newArrayList("600", "601", "603");
    public Spider() {}

    public static Spider newInstance() {
        if (Objects.isNull(spider)) {
            spider = new Spider();
        }
        return spider;
    }


    public static void main(String[] args) {

        String s = HttpHandler.sendJsonPost(ConstConfig.HTTP_POST_STOCK_CALL_AUCTION_URL, "002236");
        System.out.println(s);

//        Spider spider = Spider.newInstance();
//        try {
//            ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
//            spider.run();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    public void run() throws Exception {
        // 主要流程
        getAllCode();
    }

    public static Spider getSpider() {
        return spider;
    }


    public void getHistoryData(String code, String requestUrlIdDb) {
        // 双创不爬
        if (!isNeedGet(code)) return;
        int c = 0;
        int dateTimeStamp = (int)(Spider.getTodayStartTime() / 1000);
        if (!StringUtils.isBlank(requestUrlIdDb)) {
            dateTimeStamp = Integer.parseInt(requestUrlIdDb.split("_")[2]);
        }

        StockIndexExample example = new StockIndexExample();
        example.createCriteria().andStockCodeEqualTo(code);
        example.setOrderByClause("id");
        List<StockIndex> stockIndices = stockIndexMapper.selectByExample(example);
        if (stockIndices.size() <= 0) {
            return;
        }
        while (true) {
            JSONObject kJsonMap = null;
            String requestUrlId = "";
            try {
                // 1648137600
                String httpKUrl = ConstConfig.getHttpKUrl(code, "1", dateTimeStamp);
                requestUrlId = code + "_1_" + dateTimeStamp;
                System.out.println(httpKUrl);
                kJsonMap = HttpHandler.getHttpJson(httpKUrl, 1);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            assert kJsonMap != null;
            List<StockInfo> kData = httpHandler.getKData(kJsonMap);

            SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
            // db
            for (StockInfo stockInfo : kData) {
                stockInfo.setStockCode(code);
                stockInfo.setStockPt(s.format(stockInfo.getRecordPt()));
                stockInfo.setCompanyName(stockIndices.get(0).getCompanyName());
                stockInfo.setRequestUrlId(requestUrlId);

                // 过滤重复数据
                StockInfoExample countExample = new StockInfoExample();
                countExample.createCriteria()
                        .andRequestUrlIdEqualTo(requestUrlId)
                        .andStockPtEqualTo(s.format(stockInfo.getRecordPt()));
                if (stockInfoMapper.countByExample(countExample) > 0) {
                    System.out.println("数据: " + JSONObject.toJSONString(stockInfo) + " 已经存在\n");
                    continue;
                }

                try {
                    int insert = stockInfoMapper.insert(stockInfo);
                    if (insert > 0) {
                        System.out.println("数据: " + JSONObject.toJSONString(stockInfo) + " 插入成功\n");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("数据插入失败：" + JSONObject.toJSONString(stockInfo));
                }
            }

//            try {
//                Thread.sleep(500);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
            if (kData.size() < 200) {
                break;
            }
            c++;
            dateTimeStamp = getNDayBefore(dateTimeStamp, 200 * c);
            if (c >= 2) {
                break;
            }
//            Date time = new Date(dateTimeStamp);
//            if (time.before(new Date(getNDayBefore(new Date().getTime(), )))) {
//
//            }
        }
    }


    public Integer getNDayBefore(Integer timeStamp, int day) {
        return timeStamp - 90 * 86400;
    }

    /**
     * 获取当天的零点时间戳
     *
     * @return 当天的零点时间戳
     */
    public static long getTodayStartTime() {
        //设置时区
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis();
    }


    public void getAllCode() {
        int start = 1;
        int count = 40;
        while (true) {
            String httpCodeUrl = ConstConfig.getHttpCodeUrl(start, count);
//            System.out.println(httpCodeUrl);
            try {
                String doPut = HttpHandler.doGet(httpCodeUrl, new String(new StringBuffer(10485760)), null);
//                System.out.println(doPut);
                List<StockBasicVo> stockBasic = HttpHandler.getStockBasic(Objects.requireNonNull(HttpHandler.getJsonString(doPut, 2)));
////                System.out.println(stockBasic);
                stockBasic.forEach(info -> {
                    System.out.printf("STOCK : %s\n", info);
                    if (Objects.nonNull(info.getCode())) {
                        StockIndex stockIndex = new StockIndex();
                        stockIndex.setStockCode(info.getCode());
                        stockIndex.setCompanyName(info.getName());
                        stockIndex.setCreatedAt(new Date());
                        StockIndexExample example =  new StockIndexExample();
                        example.createCriteria().andStockCodeEqualTo(info.getCode());
                        long l = stockIndexMapper.countByExample(example);
                        if (l <= 0) {
                            stockIndex.setExchangeMarket(-1);
                            int insert = stockIndexMapper.insert(stockIndex);
                            if (insert > 0) {
                                System.out.printf("STOCK : %s, 设置成功\n", info.getCode());
                            }
                        } else {
                            int update = stockIndexMapper.updateByExampleSelective(stockIndex, example);
                            if (update > 0) {
                                System.out.printf("STOCK : %s, 设置成功\n", info.getCode());
                            }
                        }
                    }
                });
//                break;
                if (stockBasic.size() < count) {
                    break;
                }
                Thread.sleep(500);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            start++;
        }
    }


    public void getStockF10Info(String code) {
        if (code.startsWith("000") || code.startsWith("001") || code.startsWith("002") ) {
            code = "SZ" + code;
        } else if (code.startsWith("600") || code.startsWith("601") || code.startsWith("603") ) {
            code = "SH" + code;
        } else {
            return;
        }

        String httpF10Url = ConstConfig.getHttpF10Url(code);
        try {
            JSONObject httpJson = HttpHandler.getHttpJson(httpF10Url, 1);
            if (Objects.isNull(httpJson)) {
                System.out.println(code + "查询失败");
                return;
            }

            List<StockBlock> blockInfo = HttpHandler.getBlockInfo(httpJson);
            for (StockBlock stockBlock : blockInfo) {
                StockBlockExample example = new StockBlockExample();
                example.createCriteria()
                        .andStockCodeEqualTo(stockBlock.getStockCode())
                        .andBoardCodeEqualTo(stockBlock.getBoardCode());
                if (stockBlockMapper.countByExample(example) > 0) return;

                int insert = stockBlockMapper.insert(stockBlock);
                if (insert > 0) {
                    System.out.println(JSONObject.toJSONString(stockBlock) + ": 存储成功");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println();
        }
    }

    /**
     * 交易所	代码	板块
     * 主板	深证	000开头 + 4支001开头的股票
     * 主板	上证	600 601 603开头
     * 中小板	深证	002开头
     * 创业板	深证	300开头
     * 科创板	上证	688开头
     * @param code
     * @return
     */
    public Boolean isNeedGet(String code) {
        String blockCode = code.substring(0, 3);
        if (blockCode.equals("300") || blockCode.equals("688")) {
            return true;
        }

//        if (blockCode.equals("000") || codeList.contains(code) || mainBlockCodeList.contains(blockCode) || blockCode.equals("002")) {
//            return true;
//        }
         return false;
    }

}
